package cn.virens.common.db;

import java.sql.SQLException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.druid.pool.DruidDataSource;

public class DatabaseManagerImpl implements DatabaseManager {
	private final Logger logger = LoggerFactory.getLogger(DatabaseManagerImpl.class);

	private final ThreadLocal<DatabaseConnoction> local = new ThreadLocal<>();

	private final DruidDataSource dataSource = new DruidDataSource();

	private String jdbcDriverClass;
	private String jdbcPassword;
	private String jdbcUsername;
	private String jdbcUrl;

	public String getJdbcUrl() {
		return jdbcUrl;
	}

	public void setJdbcUrl(String jdbcUrl) {
		this.jdbcUrl = jdbcUrl;
	}

	public String getJdbcUsername() {
		return jdbcUsername;
	}

	public void setJdbcUsername(String jdbcUsername) {
		this.jdbcUsername = jdbcUsername;
	}

	public String getJdbcPassword() {
		return jdbcPassword;
	}

	public void setJdbcPassword(String jdbcPassword) {
		this.jdbcPassword = jdbcPassword;
	}

	public String getJdbcDriverClass() {
		return jdbcDriverClass;
	}

	public void setJdbcDriverClass(String jdbcDriverClass) {
		this.jdbcDriverClass = jdbcDriverClass;
	}

	@Override
	public DatabaseConnoction getConnection() throws SQLException {
		DatabaseConnoction conn = local.get();

		// 连接不存在 | 连接被关闭
		if (conn == null || conn.isClosed()) {
			local.set(conn = new DatabaseConnoction(dataSource));
		}

		return conn;
	}

	@Override
	public DatabaseManager execute(DatabaseQueryExecute execute) {
		DatabaseConnoction connoction = null;

		try {
			connoction = getConnection();
			connoction.setAutoCommit(true);

			// 执行查询
			execute.execute(connoction);
		} catch (Exception e) {
			logger.error("SQL异常:" + e.getMessage(), e);
		}

		return this;
	}

	@Override
	public DatabaseManager transactionExecute(DatabaseQueryExecute execute) {
		DatabaseConnoction connoction = null;

		try {
			connoction = getConnection();
			connoction.setAutoCommit(false);

			// 执行查询
			execute.execute(connoction);

			// 提交查询
			connoction.commit();
		} catch (Exception e) {
			logger.error("SQL异常:" + e.getMessage(), e);

			try {
				connoction.rollback();
			} catch (Exception e2) {
				logger.error("回滚异常:" + e2.getMessage(), e2);
			}
		}

		return this;
	}

	public void initialize() throws Exception {
		this.dataSource.setDriverClassName(getJdbcDriverClass());
		this.dataSource.setPassword(getJdbcPassword());
		this.dataSource.setUsername(getJdbcUsername());
		this.dataSource.setUrl(getJdbcUrl());

		// 配置初始化大小、最小、最大
		this.dataSource.setMinIdle(1);
		this.dataSource.setInitialSize(1);
		this.dataSource.setMaxWait(60000);// 配置获取连接等待超时的时间
		this.dataSource.setMaxActive(1000);

		this.dataSource.setFilters("slf4j");

		this.dataSource.setTestOnBorrow(false);
		this.dataSource.setTestOnReturn(false);
		this.dataSource.setTestWhileIdle(true);

		this.dataSource.setValidationQuery("SELECT 1;");
		this.dataSource.setValidationQueryTimeout(30000);

		this.dataSource.setMinEvictableIdleTimeMillis(300000);// 配置一个连接在池中最小生存的时间，单位是毫秒
		this.dataSource.setTimeBetweenEvictionRunsMillis(60000);// 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
	}

	public void destroy() throws Exception {
		this.dataSource.close();
	}

	@Override
	public void close() throws Exception {
		DatabaseConnoction connoction = local.get();
		if (connoction == null) return;

		connoction.close();
		local.remove();
	}
}
